﻿using AutoMapper;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractPcon;
using HamcoWcs.Contract.ContractSrm;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.SubTasks;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.Devices;
using HamcoWcs.Models.ForeEndModels.UITasks;
using HamcoWcs.Models.NodeInfos;
using HamcoWcs.Service.Common;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace HamcoWcs.Service.Srm.SrmTaskFinders
{
    /// <summary>
    /// 默认筛选方式<br/>
    /// 干涉>优先级>距离>时间
    /// </summary>
    public class SrmTaskFinder_Default : SrmTaskFinderBase
    {
        public override SubTask Find(SrmDto srm)
        {
            var isCanDo = srm.IsCanDo();
            if (!isCanDo) return null;
            // 特殊情况，判断堆垛机是否有有货无任务，找到已下发的任务并重发
            if (srm.IsGoods == 1)
                return GetMissingTask(srm);
            // 特殊情况，判断堆垛机是否无任务，但WCS有对应的任务
            var onProgressTask = GetOnProgressTask(srm);
            //if (onProgressTask != null && true) return onProgressTask;
            if (onProgressTask != null)
            {
                if (IsTaskCanDo(onProgressTask))
                {
                    return onProgressTask;
                }
                else
                {
                    return null;
                }
            }

            var cycleDistanceTask = GetCycleDistanceTask(srm);
            if (cycleDistanceTask != null)
            {
                return cycleDistanceTask;
            }

            var handOffTask = GetHandOffTask(srm);
            if (handOffTask != null)
            {
                return handOffTask;
            }

            // 获取该堆垛机的所有任务
            var mainTasks = _wcsDbContext.MainTasks
                .Where(x => x.TaskStatus == EnumMainTaskStatus.OnProgress.ToString()
                         || x.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                .OrderByDescending(x => x.Priority)
                .ThenByDescending(x => x.CreatedTime)
                .Include(x => x.SubTasks)
                .Where(x => x.SubTasks.Any(s => s.PlcName == srm.SrmName
                                             && s.TaskStatus == EnumSubTaskStatus.Ready.ToString()))
                .ToList();

            if (!mainTasks.Any()) return null;

            // 权重优先级计算
            foreach (var task in mainTasks)
            {
                var priority = 0;
                try
                {
                    // MES下发的优先级
                    priority = int.Parse(task.Priority);
                }
                catch (System.Exception)
                {
                    priority = 60;
                }
                //起始地优先级
                var fp = task.SrcPriority;
                //目的地优先级
                var tp = task.DesPriority;


                var subtask = task.SubTasks.FirstOrDefault(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString());

                var sBay = GetSourceBay(subtask.FromLoc, srm.Aisle.NodeName);
                // 列距离
                var distance = Math.Abs(srm.CurrentBay - sBay);

                // 计算出实际优先级
                if (distance > 7)
                {
                    task.ComplexPriority = priority + fp + tp;
                }
                else
                {
                    // _gain增益
                    task.ComplexPriority = priority + fp + tp + (10 - distance) * _gain;
                }
            }



            foreach (var task in mainTasks.OrderByDescending(x => x.ComplexPriority))
            {
                var subtask = task.SubTasks.FirstOrDefault(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString());

                //if (IsTaskCanDo(subtask) && subtask.UnitId=="PM4383")
                if (IsTaskCanDo(subtask))
                {
                    if (task.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    {
                        task.TaskStatus = EnumMainTaskStatus.OnProgress.ToString();
                        _wcsDbContext.SaveChanges();
                    }
                    return subtask;
                }
            }

            return null;
        }

        private SubTask GetHandOffTask(SrmDto srm)
        {
            // 中转储位优先搬送
            var handOffTasks = _wcsDbContext.SubTasks
                .Where(x => x.PlcName == srm.PlcName)
                .Where(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString())
                .Where(x => !string.IsNullOrEmpty(x.HandOffShelf))
                .Include(x => x.MainTask)
                .Where(x => x.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString()
                         || x.MainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString())
                .OrderByDescending(x => x.MainTask.Priority)
                .ThenByDescending(x => x.MainTask.CreatedTime)
                .ToList();

            if (handOffTasks != null && handOffTasks.Count > 0)
            {
                foreach (var htask in handOffTasks)
                {
                    if (IsTaskCanDo(htask))
                    {
                        if (htask.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                        {
                            htask.MainTask.TaskStatus = EnumMainTaskStatus.OnProgress.ToString();
                            //htask.TaskStatus = EnumSubTaskStatus.OnProgress.ToString();
                            _wcsDbContext.SaveChanges();
                        }
                        return htask;
                    }
                }
            }
            return null;
        }


        // 就近搬送
        private SubTask GetCycleDistanceTask(SrmDto srm)
        {
            if (srm.Aisle.NodeName == "CJSTW100" && (srm.CurrentBay > 4 && srm.CurrentBay < 9))
            {
                var inTask = _wcsDbContext.SubTasks
                    .Where(x => x.PlcName == srm.PlcName)
                    .Where(x => x.FromLoc == "CJRCV300" || x.FromLoc == "CJRCV400")
                    .Where(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString())
                    .Include(x => x.MainTask)
                    .Where(x => x.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString()
                             || x.MainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString())
                    .FirstOrDefault();

                if (inTask != null)
                {
                    if (inTask.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    {
                        inTask.MainTask.TaskStatus = EnumMainTaskStatus.OnProgress.ToString();
                        _wcsDbContext.SaveChanges();
                    }
                    return inTask;
                }
            }

            if (srm.Aisle.NodeName == "CJSTW100" && (srm.CurrentBay >= 25 && srm.CurrentBay <= 28))
            {
                var inTask = _wcsDbContext.SubTasks
                    .Where(x => x.PlcName == srm.PlcName)
                    .Where(x => x.FromLoc == "CJVCV700" || x.FromLoc == "CJVCV800")
                    .Where(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString())
                    .Include(x => x.MainTask)
                    .Where(x => x.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString()
                             || x.MainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString())
                    .FirstOrDefault();

                if (inTask != null)
                {
                    if (inTask.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    {
                        inTask.MainTask.TaskStatus = EnumMainTaskStatus.OnProgress.ToString();
                        _wcsDbContext.SaveChanges();
                    }
                    return inTask;
                }
            }

            if (srm.Aisle.NodeName == "CJSTW200" && (srm.CurrentBay > 3 && srm.CurrentBay < 8))
            {
                var inTask = _wcsDbContext.SubTasks
                    .Where(x => x.PlcName == srm.PlcName)
                    .Where(x => x.FromLoc == "CJRCV100" || x.FromLoc == "CJRCV200")
                    .Where(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString())
                    .Include(x => x.MainTask)
                    .Where(x => x.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString()
                             || x.MainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString())
                    .FirstOrDefault();

                if (inTask != null)
                {
                    if (inTask.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    {
                        inTask.MainTask.TaskStatus = EnumMainTaskStatus.OnProgress.ToString();
                        _wcsDbContext.SaveChanges();
                    }
                    return inTask;
                }
            }

            if (srm.Aisle.NodeName == "CJSTW200" && (srm.CurrentBay >= 54 && srm.CurrentBay <= 57))
            {
                var inTask = _wcsDbContext.SubTasks
                    .Where(x => x.PlcName == srm.PlcName)
                    .Where(x => x.FromLoc == "CJVCV300" || x.FromLoc == "CJVCV400")
                    .Where(x => x.TaskStatus == EnumSubTaskStatus.Ready.ToString())
                    .Include(x => x.MainTask)
                    .Where(x => x.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString()
                             || x.MainTask.TaskStatus == EnumMainTaskStatus.OnProgress.ToString())
                    .FirstOrDefault();

                if (inTask != null)
                {
                    if (inTask.MainTask.TaskStatus == EnumMainTaskStatus.Ready.ToString())
                    {
                        inTask.MainTask.TaskStatus = EnumMainTaskStatus.OnProgress.ToString();
                        _wcsDbContext.SaveChanges();
                    }
                    return inTask;
                }
            }
            return null;
        }

        private int GetSourceBay(string fLoc, string aisleName)
        {
            if (fLoc.IsShelf())
            {
                var b = fLoc.Substring(2, 3);
                try
                {
                    return int.Parse(b);
                }
                catch (Exception)
                {
                    return 0;
                }
            }
            else
            {
                if (fLoc == "CJRCV100") return 5;
                if (fLoc == "CJRCV200") return 7;
                if (fLoc == "CJRCV300") return 6;
                if (fLoc == "CJRCV400") return 8;

                if (fLoc == "CJVCV100" && aisleName == "CJSTW100") return 6;
                if (fLoc == "CJVCV100" && aisleName == "CJSTW200") return 15;
                if (fLoc == "CJVCV200" && aisleName == "CJSTW100") return 28;
                if (fLoc == "CJVCV200" && aisleName == "CJSTW200") return 37;

                if (fLoc == "CJVCV300") return 55;
                if (fLoc == "CJVCV400") return 57;

                if (fLoc == "CJVCV700") return 26;
                if (fLoc == "CJVCV800") return 28;
            }
            return 0;
        }



        //private readonly IBaseConfigService _config;
        private int _gain = 3;
        public SrmTaskFinder_Default(IBaseConfigService config, AutomaticStorageInfo asrs, WcsDbContext wcsDbContext, IMapper mapper, IPathService pathService, IPconBaseService pconBaseService, IBaseSrmTaskService srmTaskService, ILocationService locationService)
            : base(wcsDbContext, mapper,config, pathService, pconBaseService, srmTaskService, locationService, asrs)
        {
            var a = _config.TryGetConfigValue("DISTANCEGAIN", out string g);

            try
            {
                if (a)
                {
                    _gain = int.Parse(g);
                }
            }
            catch (Exception)
            {
                _gain = 3;
            }
        }

        public override string Policy => "Default";
    }
}
